//
//  JxrPreview.c
//  JxrQuickLookPlugin
//
//  Created by Brian Hoary on 01/05/2013.
//  Copyright (c) 2013 Brian Hoary. All rights reserved.
//
#include <CoreFoundation/CoreFoundation.h>
#include <CoreServices/CoreServices.h>
#include <QuickLook/QuickLook.h>
#include <JXRTest.h>
#include "JxrPreview.h"

char * CFStringCopyUTF8String1(CFStringRef aString) {
    if (aString == NULL) {
        return NULL;
    }
    
    CFIndex length = CFStringGetLength(aString);
    CFIndex maxSize =
    CFStringGetMaximumSizeForEncoding(length,
                                      kCFStringEncodingUTF8);
    char *buffer = (char *)malloc(maxSize);
    if (CFStringGetCString(aString, buffer, maxSize,
                           kCFStringEncodingUTF8)) {
        return buffer;
    }
    return NULL;
}


OSStatus GenerateJxrPreview(QLThumbnailRequestRef thumbnail, QLPreviewRequestRef preview, CFURLRef url, CFDictionaryRef options, CGSize* maxSize)
{
    ERR err = WMP_errSuccess;
    
    PKFactory* pFactory = NULL;
    PKCodecFactory* pCodecFactory = NULL;
    PKImageDecode* pDecoder = NULL;
    PKFormatConverter* pConverter = NULL;
    
    Call(PKCreateFactory(&pFactory, PK_SDK_VERSION));
    
    Call(PKCreateCodecFactory(&pCodecFactory, WMP_SDK_VERSION));
    Call(pCodecFactory->CreateDecoderFromFile(CFStringCopyUTF8String1(CFURLCopyPath(url)), &pDecoder));
    
    if(maxSize != NULL){//if creating thumbnail
        int sizeDivider = 0;
        while((pDecoder->WMP.wmiI.cHeight>>sizeDivider > maxSize->height ||pDecoder->WMP.wmiI.cWidth>>sizeDivider > maxSize->width)&&sizeDivider<4){
            sizeDivider++;
        }
        pDecoder->WMP.wmiI.cThumbnailWidth = pDecoder->WMP.wmiI.cWidth>>sizeDivider;
        pDecoder->WMP.wmiI.cThumbnailHeight = pDecoder->WMP.wmiI.cHeight>>sizeDivider;
        if(pDecoder->WMP.wmiI.cfColorFormat == YUV_420 || pDecoder->WMP.wmiI.cfColorFormat == YUV_422){ // unsupported thumbnail format
            pDecoder->WMP.wmiI.cfColorFormat = YUV_444;
        }
    }
    else{
        pDecoder->WMP.wmiI.cThumbnailWidth = pDecoder->WMP.wmiI.cWidth;
        pDecoder->WMP.wmiI.cThumbnailHeight = pDecoder->WMP.wmiI.cHeight;
    }
    
    //Create color converter
    Call(pCodecFactory->CreateFormatConverter(&pConverter));
    Call(pConverter->Initialize(pConverter, pDecoder, NULL, GUID_PKPixelFormat24bppRGB));
    
    PKRect rect = {0,0,0,0};
    rect.Width = (I32)(pDecoder->WMP.wmiI.cThumbnailWidth);
    rect.Height = (I32)(pDecoder->WMP.wmiI.cThumbnailHeight);
    
    U8 *pixelBuffer = NULL;
    
    PKAllocAligned(&pixelBuffer, rect.Width * 3 * rect.Height, 128);
    
    Call(pConverter->Copy(pConverter, &rect, pixelBuffer, rect.Width * 3 ));
    
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CFDataRef rgbData = CFDataCreate(NULL, pixelBuffer, rect.Height * rect.Width * 3);
    CGDataProviderRef provider = CGDataProviderCreateWithCFData(rgbData);
    CGImageRef image = CGImageCreate(rect.Width, rect.Height, 8, 24, rect.Width * 3, colorSpace, kCGBitmapByteOrderDefault, provider, NULL, true, kCGRenderingIntentDefault);
    
    CGContextRef cgContext = NULL;
    if(thumbnail!=NULL){
        QLThumbnailRequestSetImage(thumbnail, image, options);}
    else if(preview!=NULL){
        cgContext = QLPreviewRequestCreateContext(preview, CGSizeMake(rect.Width, rect.Height), TRUE, options);
        
        CGContextDrawImage(cgContext, CGRectMake(0,0,rect.Width, rect.Height), image);
        QLPreviewRequestFlushContext(preview, cgContext);
    
    }
    
    CGColorSpaceRelease(colorSpace);
    CFRelease(rgbData);
    CGDataProviderRelease(provider);
    CGImageRelease(image);
    CGContextRelease(cgContext);
    
Cleanup:
    
    return 0;
}
